package http

import (
	"context"
	"errors"
	"fmt"
	"fsdvgw/repo"
	"fsdvgw/support_device/dumu"
	"github.com/gin-gonic/gin"
	"net/http"
	"strconv"
	"time"
)

var srv *http.Server

func Start() {
	r := gin.New()
	r.POST("/callback/dumu/heartbeat", dumu.HandleHeartbeatCallback)
	r.POST("/callback/dumu/recognize", dumu.HandleRecognizeCallback)
	r.POST("/device", addDevice)
	r.PUT("/device", updateDevice)
	r.DELETE("/device/:id", deleteDevice)
	r.GET("/", getDevice)

	srv = &http.Server{
		Addr:    ":8081",
		Handler: r,
	}
	go func() {
		if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
			panic(err)
		}
	}()

}

func Stop() {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := srv.Shutdown(ctx); err != nil {
		fmt.Println(err)
	}
}

func getDevice(c *gin.Context) {
	all := repo.GetAll()
	html := "<table border=\"1\"><tr>"
	html += "<th>ID</th>"
	html += "<th>Model</th>"
	html += "<th>DeviceId</th>"
	html += "<th>IP</th>"
	html += "<th>Context</th>"
	html += "<th>IsDynamic</th>"
	html += "<th>LastHeartbeatTime</th>"
	html += "<th>Online</th>"
	html += "</tr>"
	for _, ds := range all {
		line := "<tr>"
		line += "<td>" + ds.ID + "</td>"
		line += "<td>" + ds.Model + "</td>"
		line += "<td>" + ds.DeviceId + "</td>"
		line += "<td>" + ds.IP + "</td>"
		line += "<td>" + ds.Context + "</td>"
		line += "<td>" + strconv.FormatBool(ds.IsDynamic) + "</td>"
		line += "<td>" + ds.LastHeartbeatTime.Format("15:04:05") + "</td>"
		line += "<td>" + strconv.FormatBool(ds.Online) + "</td>"
		line += "</tr>"
		html += line
	}
	html += "</table>"
	c.Writer.WriteHeader(http.StatusOK)
	c.Writer.WriteString(html)
}

func addDevice(c *gin.Context) {
	req := new(AddDeviceRequest)
	err := c.ShouldBindJSON(req)
	if err != nil {
		c.JSON(http.StatusBadRequest, &response{false, err.Error()})
		return
	}
	err = repo.CreateStaticDevice(&repo.StaticDeviceParam{
		Model:   req.Model,
		IP:      req.IP,
		Context: req.Password,
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, &response{false, err.Error()})
		return
	}
	c.JSON(http.StatusOK, &response{true, ""})
}

func deleteDevice(c *gin.Context) {
	id := c.Param("id")
	if id == "" {
		c.JSON(http.StatusBadRequest, &response{false, ""})
		return
	}

	err := repo.DeleteDevice(id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, &response{false, err.Error()})
		return
	}
	c.JSON(http.StatusOK, &response{true, ""})
}

func updateDevice(c *gin.Context) {
	req := new(UpdateDeviceRequest)
	err := c.ShouldBindJSON(req)
	if err != nil {
		c.JSON(http.StatusBadRequest, &response{false, err.Error()})
		return
	}
	err = repo.UpdateStaticDevice(&repo.Dev{
		ID:      req.ID,
		Model:   req.Model,
		IP:      req.IP,
		Context: req.Password,
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, &response{false, err.Error()})
		return
	}
	c.JSON(http.StatusOK, &response{true, ""})
}
